package com.sktlab.bizconfmobile.adapter;

import java.util.ArrayList;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.sktlab.bizconfmobile.R;
import com.sktlab.bizconfmobile.activity.AccountSettingActivity;
import com.sktlab.bizconfmobile.activity.AddAccountActivity;
import com.sktlab.bizconfmobile.activity.ConferenceActivity;
import com.sktlab.bizconfmobile.activity.OrderConfActivity;
import com.sktlab.bizconfmobile.fragment.HomeFragment;
import com.sktlab.bizconfmobile.interfaces.ILoadingDialogCallback;
import com.sktlab.bizconfmobile.model.ConfControl;
import com.sktlab.bizconfmobile.model.ConferenceAccount;
import com.sktlab.bizconfmobile.model.Constant;
import com.sktlab.bizconfmobile.model.db.AccountsDBAdapter;
import com.sktlab.bizconfmobile.model.db.AccountsDbTable;
import com.sktlab.bizconfmobile.model.manager.AccountsManager;
import com.sktlab.bizconfmobile.model.manager.CommunicationManager;
import com.sktlab.bizconfmobile.util.Util;

public class ConfAccountAdapter extends BaseAdapter 
				implements DialogInterface.OnClickListener,
								ILoadingDialogCallback{
	
	public static final String TAG = "ConfAccountAdapter";
	
	private int mLayoutId;
	private Activity mActivity;
	private LayoutInflater mInflater;
	private ArrayList<ConferenceAccount> mConfAccountDatas;
	private SparseArray<LinearLayout> map;
	private ConferenceAccount mSelectedAccount;

	private int mDialogType;
	//account database
	private AccountsDBAdapter mAccountDb;
	
	private int mFunctionType = -1;
	
	//reset dialog type
	private static final int DIALOG_TYPE_RESET = 0;
	// start conference dialog type
	private static final int DIALOG_TYPE_START_ACCOUNT = 1;
	//delete conference dialog type
	private static final int DIALOG_TYPE_DEL_ACCOUNT = 2;
	
	
	public ConfAccountAdapter(Activity ctx,int layoutId) {
		
		mActivity = ctx;
		mLayoutId = layoutId;
		mConfAccountDatas = new ArrayList<ConferenceAccount>();	
		
		init();
	}
	
	public ConfAccountAdapter(Activity ctx,int layoutId, ArrayList<ConferenceAccount> list) {
		
		mActivity = ctx;
		mLayoutId = layoutId;
		mConfAccountDatas = list;
		
		init();
	}
	
	private void init(){
		
		mInflater = (LayoutInflater) mActivity
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		map = new SparseArray<LinearLayout>();
		
		mAccountDb = new AccountsDBAdapter(AccountsDbTable.ACCOUNTS_DB_TABLE, 
				AccountsDbTable.getAllColumns());
	}
	
	public void setData(ArrayList<ConferenceAccount> datas) {
		
		mConfAccountDatas = datas;
		notifyDataSetChanged();
	}
	
	@Override
	public int getCount() {
		
		return mConfAccountDatas.size();
	}

	@Override
	public Object getItem(int position) {
		
		return null;
	}

	@Override
	public long getItemId(int position) {
	
		return 0;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		
		ViewHolder vh = null;
		
		if (convertView == null) {
			
			convertView = mInflater.inflate(mLayoutId, null);
			
			vh = new ViewHolder();
			
			vh.layoutTvs = (LinearLayout)convertView
						.findViewById(R.id.layout_account_info);
			
			vh.tvConfAccountName = (TextView)convertView
						.findViewById(R.id.tv_conf_name);
			vh.tvConfCode = (TextView)convertView
						.findViewById(R.id.tv_conf_code);
			
			vh.layoutBts = (LinearLayout)convertView
						.findViewById(R.id.layout_bt_module);
			
			vh.btEdit = (Button) convertView
						.findViewById(R.id.bt_edit);
			vh.btStart = (Button) convertView
					.findViewById(R.id.bt_start);
			vh.btDel = (Button) convertView
					.findViewById(R.id.bt_del);
			
			convertView.setTag(vh);
		} else {
			vh = (ViewHolder) convertView.getTag();
		}
		
		if (mConfAccountDatas == null) {
			
			return null;
		}
		
		ConferenceAccount ConfAccount = mConfAccountDatas.get(position);
		
		if (ConfAccount == null) {
			
			return null;
		}
		
		//when refresh list view ,we should hide the button layout in the first time
		vh.layoutBts.setVisibility(View.GONE);
		
		String ConfAccountName = ConfAccount.getConfAccountName();
		String ConfCode = ConfAccount.getConfCode();
				
		vh.tvConfAccountName.setText(ConfAccountName);
		vh.tvConfCode.setText(ConfCode);
		
		map.put(position, vh.layoutBts);
		
		final int pos = position;
		
		final Button fuc = vh.btStart;
		
		vh.layoutTvs.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {

				switch (mFunctionType) {

				case HomeFragment.TAB_JOIN_CONF:
					fuc.setText(R.string.join_conf);
					break;
					
				case HomeFragment.TAB_START_CONF:
					fuc.setText(R.string.start_conf);
					break;
				}

				isShowFunctionBts(pos);
			}
		});
		
		vh.btEdit.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				
				startEditAccountActivity();
			}
		});
		
		vh.btStart.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
							
				mDialogType = DIALOG_TYPE_START_ACCOUNT;
				showDialog();
			}
		});
		
		final LinearLayout layoutButtons = vh.layoutBts;
		
		vh.btDel.setOnClickListener(new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			
			mDialogType = DIALOG_TYPE_DEL_ACCOUNT;
			
			rmAccount();		
			layoutButtons.setVisibility(View.GONE);
		}
	});
		return convertView;
	}
	
	/**
	 * whether to show the function buttons
	 * @param pos
	 */
	private void isShowFunctionBts(int pos){
		
		LinearLayout layout = map.get(pos);
		mSelectedAccount = mConfAccountDatas.get(pos);
		
		do {
			
			if (mFunctionType == AccountSettingActivity.SETTING_ACCOUNT_LIST) {
				
				startEditAccountActivity();
				break;
			}
			
			//order conference module always hide the functions module
			if(mFunctionType == HomeFragment.TAB_ORDER_CONF) {
				
				startOrderConfActivity();
				break;
			}
			
			if(layout.getVisibility() == View.GONE) {
				
				layout.setVisibility(View.VISIBLE);
				break;
			}
				
			layout.setVisibility(View.GONE);
		
		}while(false);
	}
	
	/**
	 * 
	 */
	private void startOrderConfActivity(){
		
		Intent intent = new Intent();
		intent.setClass(mActivity, OrderConfActivity.class);
		intent.putExtra(Constant.KEY_OF_CONF_ACCOUNT_ID, mSelectedAccount.getAccountId());
		
		mActivity.startActivity(intent);
	}
	
	/**
	 * start edit account activity
	 */
	private void startEditAccountActivity() {
		Intent intent = new Intent();
		intent.setClass(mActivity, AddAccountActivity.class);
		intent.setAction(AddAccountActivity.ACTION_EDIT_ACCOUNT);
		intent.putExtra(Constant.KEY_OF_CONF_ACCOUNT_ID, mSelectedAccount.getAccountId());
		
		mActivity.startActivity(intent);
	}
	
	/**
	 * remove the selected account
	 */
	private void rmAccount() {
		
		mAccountDb.open();
		
		boolean rmResult = mAccountDb.deleteObject(mSelectedAccount.getAccountId());
		
		int index = AccountsManager.getInstance().removeAccount(mSelectedAccount);
		
		if(rmResult && index != -1) {
			
			Util.shortToast(mActivity, "remove account success");
		}
		
		mAccountDb.close();
		
	
		notifyDataSetChanged();
	}
	
	/**
	 * show a dialog to user to confirm the start conference operation
	 */
	private void showDialog() {

		if (mSelectedAccount != null) {

			String title = mSelectedAccount.getConfAccountName();

			new AlertDialog.Builder(mActivity).setMessage(title)
					.setTitle(title)
					.setIcon(android.R.drawable.ic_dialog_alert)
					.setPositiveButton(android.R.string.ok, this)
					.setNegativeButton(android.R.string.cancel, this).show();
		}
	}
	
	/**
	 * connect to the server to start a conference
	 * @return
	 */
	private boolean connectToStartConf(){
		
		boolean isOpenSuccess = false;
		
		CommunicationManager.getInstance().setActiveAccount(mSelectedAccount);
		
		ConfControl.getInstance().startConf(mActivity, this);
		
		return isOpenSuccess;
	}
	
	/**
	 * when user selected a operation in the confirm to start conference dialog
	 */
	@Override
	public void onClick(DialogInterface dialog, int which) {
		
		if (which == DialogInterface.BUTTON_POSITIVE) {
        	switch(mDialogType) {
        		case DIALOG_TYPE_START_ACCOUNT:
        			
        			connectToStartConf();
        			break;
        			
        		case DIALOG_TYPE_DEL_ACCOUNT:
        			
        			break;
        			
        		default:
        			break;
        	}
        }
        
       mDialogType = DIALOG_TYPE_RESET;
	}
	
	class ViewHolder {
		private TextView tvConfAccountName;
		private TextView tvConfCode;
		private LinearLayout layoutTvs;
		private Button btEdit;
		private Button btStart;
		private Button btDel;
		private LinearLayout layoutBts;
	}
	
	/**
	 * connect to server success to start a conference, including initialize of the session~
	 * when everything is done, this method will be called to enter the conference operate view
	 */
	@Override
	public void onSuccessDone() {
		
		Intent intent = new Intent();
		
		intent.setClass(mActivity, ConferenceActivity.class);
		intent.putExtra(Constant.KEY_OF_CONF_ACCOUNT_ID, mSelectedAccount.getAccountId());
		
		mActivity.startActivity(intent);
	}
	
	/**
	 * connect to server error to start a conference, can show some message here to remind the user
	 */
	@Override
	public void onDoneWithError() {
		
		ConfControl.getInstance().disconnectToServer();
		Util.shortToast(mActivity, "connect conference failed");
	}
	
	/**
	 * get the type of current operation, there are three selection: Start Conference; Order Conference; Join Conference
	 * @return
	 */
	public int getFunctionType() {
		return mFunctionType;
	}

	public void setFunctionType(int mFunctionType) {
		this.mFunctionType = mFunctionType;
	}
}
